﻿using CWCS.BLL.NTIScModbus;
using CWCS.Common.GeneralUtils;
using CWCS.Common.Log;
using CWCS.Entity.SRM;
using SuperWebSocket;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace CWCS.BLL.WebsocketCommon
{
    public class WebSocketHelper
    {
        private static WebSocketServer webSocketServer = new WebSocketServer();
        static List<WebSocketSession> sessionList = new List<WebSocketSession>();
        static List<WebSocketSession> errorSessionList = new List<WebSocketSession>();

        static Dictionary<string, WebSocketSession> dicSession = new Dictionary<string, WebSocketSession>();
        static WebSocketConfiguration config = new WebSocketConfiguration();
        //private BLLConvery bll = new BLLConvery();
        private BLL.ConveryBLL bll = new BLL.ConveryBLL();
        private ModbusBLLSRMRun taskbll = new ModbusBLLSRMRun();
        private LogHelper staManualLog = new LogHelper("staManualLog");
        private LogHelper scManualLog = new LogHelper("scManualLog");

        static int locked = 0;
        public void WebSocketStart()
        {
            Console.WriteLine("WebSocket服务端准备开始监听");

            if (webSocketServer == null)
            {
                webSocketServer = new WebSocketServer();
            }
            config.Ip = ReadJsonHelper.ReadJsonFile("Ip");
            config.Port = Convert.ToInt32(ReadJsonHelper.ReadJsonFile("Port"));
            webSocketServer.NewSessionConnected += WebSocketServer_NewSessionConnected;
            webSocketServer.NewMessageReceived += WebSocketServer_NewMessageReceived;
            webSocketServer.SessionClosed += WebSocketServer_SessionClosed;

            if (!webSocketServer.Setup(config.Ip, config.Port))
            {
                Console.WriteLine("设置服务监听失败！");
            }

            if (!webSocketServer.Start())
            {
                Console.WriteLine("启动服务监听失败！");
            }

            Console.WriteLine("启动服务监听成功！");


        }

        private void WebSocketServer_NewSessionConnected(WebSocketSession session)
        {
            Console.WriteLine("客户端: " + session.SessionID + " 连接了服务端");
            if (!sessionList.Any(x => x == session))
            {
                sessionList.Add(session);
            }
        }

        private void WebSocketServer_NewMessageReceived(WebSocketSession session, string value)
        {
            Console.WriteLine("接收到客户端: " + session.SessionID + " 的消息: " + value);

            //#region 验证哪个WCS客户端发的，并绑定session
            //if (value.StartsWith("WCS"))
            //{
            //    if (dicSession.ContainsKey(value))
            //    {
            //        dicSession[value] = session;
            //    }
            //    else
            //    {
            //        dicSession.Add(value, session);
            //    }
            //}
            //#endregion
            if (value.StartsWith("ReadStation")) //读取站台信息
            {
                string newValue = value.Replace("ReadStation", "");
                bll.ReadStationInfoByclient(session, newValue);
            }
            if (value.StartsWith("WriteStation")) //写入站台信息
            {
                string newValue = value.Replace("WriteStation", "");
                string[] strArray = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(newValue);
                string[] newstrArray = new string[strArray.Length - 1];
                Array.Copy(strArray, 1, newstrArray, 0, newstrArray.Length);
                bool result = bll.WriteStationInfo(STACommand.ReWrite, newstrArray, newstrArray[0], 0, 40);
                if (newstrArray[5] != "1" && newstrArray[5] != "0" && newstrArray[5] != "9999")
                {
                    if (!bll.UpdateItempalletTostation(newstrArray[2], newstrArray[5]))
                    {
                        staManualLog.Info("手动修改目标地址,更新Itempallet表中托盘:'" + newstrArray[3] + "'的目标地址失败,请检查该托盘是否初始化!");
                    }
                }
                staManualLog.Info("用户:" + strArray[0] + "修改站台:" + newstrArray[0] + "数据为:任务号" + newstrArray[1] + "托盘条码：" + newstrArray[2] + "货物类型：" + newstrArray[3] + "目标地址：" + newstrArray[5] + (result ? "成功" : "失败"));
                var WriteResultString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
                SendMsgBySession(session, "WriteStation" + WriteResultString);
            }
            if (value.StartsWith("WriteScanStation")) //补码
            {
                string newValue = value.Replace("WriteScanStation", "");
                string[] strArray = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(newValue);
                bool result = bll.WriteScanInfo(strArray[2], strArray[1]);
                staManualLog.Info("用户:" + strArray[0] + "手动补码成功!站台:" + strArray[1] + ",条码:" + strArray[2]);
                var WriteResultString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
                SendMsgBySession(session, "WriteScanStation" + WriteResultString);
            }
            if (value.StartsWith("ClearStation")) //清空站台信息
            {
                string newValue = value.Replace("ClearStation", "");
                string[] strArray = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(newValue);
                string[] newstrArray = new string[strArray.Length - 1];
                Array.Copy(strArray, 1, newstrArray, 0, newstrArray.Length);
                bool result = bll.WriteStationInfo(STACommand.ReWrite, newstrArray, newstrArray[0], 0, 40);
                staManualLog.Info("用户:" + strArray[0] + "清空站台:" + newstrArray[0] + "信息" + (result ? "成功" : "失败"));

                var WriteResultString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
                SendMsgBySession(session, "ClearStation" + WriteResultString);
            }
            if (value.StartsWith("MoveStation")) //转移站台信息
            {
                string newValue = value.Replace("MoveStation", "");
                string[] strArray = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(newValue);
                string[] newstrArray = new string[strArray.Length - 2];
                Array.Copy(strArray, 2, newstrArray, 0, newstrArray.Length);
                bool result = bll.WriteStationInfo(STACommand.ReWrite, newstrArray, newstrArray[0], 0, 40);
                staManualLog.Info("用户:" + strArray[0] + "将站台:" + strArray[1] + "转移至站台:" + newstrArray[0] + ",数据为任务号" + newstrArray[1] + "托盘条码：" + newstrArray[2] + "货物类型：" + newstrArray[3] + "目标地址：" + newstrArray[5] + (result ? "成功" : "失败"));
                var WriteResultString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
                SendMsgBySession(session, "MoveStation" + WriteResultString);
            }
            if (value.StartsWith("ExceptionStation")) //一键排异
            {
                string newValue = value.Replace("ExceptionStation", "");
                string[] strArray = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(newValue);
                string[] newstrArray = new string[strArray.Length - 1];
                Array.Copy(strArray, 1, newstrArray, 0, newstrArray.Length);
                bool result = bll.WriteStationInfo(STACommand.ReWrite, newstrArray, newstrArray[0], 0, 40);
                if (!bll.UpdateItempalletTostation(newstrArray[2], newstrArray[5]))
                {
                    staManualLog.Info("一键排异,更新Itempallet表中托盘:'" + newstrArray[2] + "'的目标地址失败,请检查该托盘是否初始化!");
                }
                staManualLog.Info("用户:" + strArray[0] + "将站台:" + newstrArray[0] + "托盘一键排异" + (result ? "成功" : "失败"));
                var WriteResultString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
                SendMsgBySession(session, "ExceptionStation" + WriteResultString);
            }
            if (value.StartsWith("UpdateMode")) //修改投盘模式
            {
                string newValue = value.Replace("UpdateMode", "");
                string[] str = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(newValue);
                BLLBase.Mode = int.Parse(str[2]);
                BLLBase.modeTime = DateTime.Now;
                BLLBase.modeName = str[1];
                staManualLog.Info("用户:" + str[0] + "将投盘模式修改成:" + BLLBase.modeName);
            }
            if (value.StartsWith("OCVMAS")) //修改OCVMAS
            {
                string newValue = value.Replace("OCVMAS", "");
                string[] str = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(newValue);
                BLLBase.ocvMsaStatus = bool.Parse(str[1]);
                if (!BLLBase.ocvMsaStatus)
                    BLLBase.ocvMsa.Clear();
                staManualLog.Info("用户:" + str[0] + (BLLBase.ocvMsaStatus ? "开启" : "关闭") + "MSA功能");
            }
            if (value.StartsWith("UpdateSCMode")) //修改堆垛机模式
            {
                string newValue = value.Replace("UpdateSCMode", "");
                SCMode sCMode = Newtonsoft.Json.JsonConvert.DeserializeObject<SCMode>(newValue);
                BLLBase.modeFlag[sCMode.scno] = sCMode.sCTaskMode;
                scManualLog.Info("用户:" + sCMode.user + "将WCS模式改为:" + (BLLBase.modeFlag[sCMode.scno] == SCTaskMode.Manual ? "手动" : "自动"));
            }
            if (value.StartsWith("ChangeTaskType")) //修改堆垛机任务模式    
            {
                string newValue = value.Replace("ChangeTaskType", "");
                ChangeTaskType changeTaskType = Newtonsoft.Json.JsonConvert.DeserializeObject<ChangeTaskType>(newValue);
                bool result = taskbll.UpdateTaskModeInfo(changeTaskType.scno, changeTaskType.taskType);
                string log = string.Format("用户:" + changeTaskType.user + "更改堆垛机任务模式：堆垛机号{0}，更改后模式为{1}", changeTaskType.scno, changeTaskType.taskType);
                scManualLog.Info(log);
                var WriteResultString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
                SendMsgBySession(session, "ChangeTaskType" + WriteResultString);
            }
            if (value.StartsWith("ChangeForkNo")) //修改堆垛机货叉类型 
            {
                string newValue = value.Replace("ChangeForkNo", "");
                ChangeForkNo changeForkNo = Newtonsoft.Json.JsonConvert.DeserializeObject<ChangeForkNo>(newValue);
                bool result = taskbll.UpdateForkNoInfo(changeForkNo.scno, changeForkNo.forkNo);
                string log = string.Format("用户:" + changeForkNo.user + "更改堆垛机货叉类型：堆垛机号{0}，更改后货叉为{1}", changeForkNo.scno, changeForkNo.forkNo);
                scManualLog.Info(log);
                var WriteResultString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
                SendMsgBySession(session, "ChangeForkNo" + WriteResultString);
            }
            if (value.StartsWith("SendTask")) //发送堆垛机指令
            {
                string newValue = value.Replace("SendTask", "");
                SendTask sendTask = Newtonsoft.Json.JsonConvert.DeserializeObject<SendTask>(newValue);
                bool result = taskbll.SendTask(sendTask.scno,sendTask.taskno,sendTask.taskno2,sendTask.sourceAddress,sendTask.targetAddress,sendTask.cmdType,"0",sendTask.forkNo);
                string log = string.Format("用户:" + sendTask.user + "手动下发堆垛机{0}指令：{1}，货叉1任务{2}，货叉2任务{3}，起始地址{4}，目标地址{5},货叉{6}", sendTask.scno, sendTask.cmdType, sendTask.taskno, sendTask.taskno2, sendTask.sourceAddress, sendTask.targetAddress, sendTask.forkNo);
                scManualLog.Info(log);
                var WriteResultString = Newtonsoft.Json.JsonConvert.SerializeObject(result);
                SendMsgBySession(session, "SendTask" + WriteResultString);
            }
        }

        private void WebSocketServer_SessionClosed(WebSocketSession session, SuperSocket.SocketBase.CloseReason value)
        {
            Console.WriteLine("客户端 " + session.SessionID + " 已断开连接");
            if (sessionList.Any(x => x == session))
            {
                sessionList.Remove(session);
            }
        }

        public static void SendMsgToRemotePoint(string msg)
        {
            if (Interlocked.Exchange(ref locked, 1) == 0)
            {
                int index = 0;
                foreach (var ses in sessionList)
                {
                    index++;
                    if (ses != null)
                    {
                        try
                        {
                            ses.Send(msg);
                        }
                        catch(Exception e)
                        {
                            errorSessionList.Add(ses);// = null;
                        }
                    }
                }
                foreach (var session in errorSessionList)
                {
                    if (sessionList.Any(x => x == session))
                    {
                        //sessionList.Remove(session);
                    }
                }
                errorSessionList = new List<WebSocketSession>();
                locked = 0;
            }

        }

        public static void SendMsgBySession(WebSocketSession session, string msg)
        {
            session.Send(msg);
        }

    }
}
